home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
satellit
/
vstsrc
/
vst.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-02
|
44KB
|
1,406 lines
/*
* %W% %E% %U% [EXTREL_1.2]
*
* VersaTrack orbit calculations are based on those that appear in Dr. Manfred
* Bester's sattrack program (the Unix(tm) versions 1 and 2).
*
* The data from which the maps where generated come from "xsat", an
* X-Windows program by David A. Curry (N9MSW).
*
* Site coordinates come from various sources, including a couple of
* World Almanacs, and also from both of the programs mentioned above.
*
* The following are authors' applicable copyright notices:
*
*
* Copyright (c) 1992, 1993, 1994 Manfred Bester. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for educational, research and non-profit purposes, without
* fee, and without a written agreement is hereby granted, provided that the
* above copyright notice and the following three paragraphs appear in all
* copies.
*
* Permission to incorporate this software into commercial products may be
* obtained from the author, Dr. Manfred Bester, 1636 M. L. King Jr. Way,
* Berkeley, CA 94709, USA.
*
* IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
* SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
* THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR HAS BEEN ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
*
* Copyright 1992 by David A. Curry
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation. The
* author makes no representations about the suitability of this software for
* any purpose. It is provided "as is" without express or implied warranty.
*
* David A. Curry, N9MSW
* Purdue University
* Engineering Computer Network
* 1285 Electrical Engineering Building
* West Lafayette, IN 47907
* davy@ecn.purdue.edu
*
* VersaTrack Copyright (c) 1993, 1994 Siamack Navabpour. All Rights Reserved.
*
* Permission is hereby granted to copy, modify and distribute VersaTrack
* in whole, or in part, for educational, non-profit and non-commercial use
* only, free of charge or obligation, and without agreement, provided that
* all copyrights and restrictions noted herein are observed and followed, and
* additionally, that this and all other copyright notices listed herein
* appear unaltered in all copies and in all derived work.
*
* This notice shall not in any way void or supersede any of the other authors
* rights or privileges.
*
* VersaTrack IS PRESENTED FREE AND "AS IS", WITHOUT ANY WARRANTY OR SUPPORT.
* YOU USE IT AT YOUR OWN RISK. The author(s) shall not be liable for any
* direct, indirect, incidental, or consequential damage, loss of profits or
* other tangible or intangible losses or benefits, arising out of or related
* to its use. VersaTrack carries no warranty, explicit or implied, including
* but not limited to those of merchantablity and fitness for a particular
* purpose.
*
* Siamack Navabpour, 12342 Hunter's Chase Dr. Apt. 2114, Austin, TX 78729.
* sia@bga.com or sia@realtime.com.
*/
#include <windows.h>
#include <winsock.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "resource.h"
#include "vstdefs.h"
#include "constant.h"
#include "vsttype.h"
#include "vstextrn.h"
#include "vstdib.h"
/*
* Global vars
*/
char textbuf[BUFLEN];
char tmpbuf[BUFLEN];
char msgbuf[BUFLEN];
char string[BUFLEN];
char timeZoneName[9];
char timeZoneHrs[11];
char mapname[16];
char datadir[96];
char SiteName[64];
char VersionStr[40];
char sitefilename[NAMELEN];
char satfilename[NAMELEN];
char activefilename[NAMELEN];
char modesfilename[NAMELEN];
char gtrfilename[NAMELEN];
char mapfilename[NAMELEN];
char rotatorfilename[NAMELEN];
char radiofilename[NAMELEN];
char dllname[NAMELEN] = { "DBREAD.DLL" } ;
char *dllloadmsg = "VersaTrack: Cannot find/load DBREAD.DLL";
char *dllinvalidmsg = "Module not found in DBREAD.DLL";
#if 0 /* NOT CURRENTLY USED */
#define UC(x) ((unsigned char)(x))
unsigned char EpochString[18] = { /* */
UC(0x38), UC(0x86), UC(0x3b), UC(0x66),
UC(0x6c), UC(0xee), UC(0xbc), UC(0x24),
UC(0xc5), UC(0xae), UC(0x37), UC(0x83),
UC(0xde), UC(0xc1), UC(0xbe), UC(0x41)
};
#endif
/*
* Color table. Use 16-color VGA.
*/
static
COLORREF DefColors[16] = {
0x00000000, 0x0000007f, 0x00007f00, 0x00007f7f,
0x007f0000, 0x007f007f, 0x007f7f00, 0x007f7f7f,
0x00bfbfbf, 0x000000ff, 0x0000ff00, 0x0000ffff,
0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff
};
static
mapsuffix_t mapSuffix[] = {
640, 480, "64",
800, 600, "86",
1024, 768, "17",
0, 0,
};
double minElevation = 0.0;
double duration = 1.0;
double stepTime = 30.0 / SPD;
double startTime = -1;
double stopTime = -1;
double timeZone = 0;
double ScaleX;
double ScaleY;
site_t **siteInfo; /* vector of ptrs to sorted sites */
satellite_t **satInfo; /* vector of ptrs to element sets */
select_t *selInfo; /* list of user's favorite sat/site tuples */
select_t *currentSel; /* currently selected entry in the active list */
rotinfo_t *rotInfo; /* linked list of rotator drivers */
radinfo_t *radInfo; /* linked list of radio drivers */
FILE *gtrFile; /* File ptr for ground track report file */
HANDLE hInst; /* VersaTrack instance handle */
HANDLE gtr_thread_handle; /* for thread drawing a groundtrack */
int Inst; /* int version of hInst. */
HWND Gwnd; /* global copy of our window handle */
HWND rsthwnd; /* handle of Rise Time query dialog box*/
HWND hDlgMenu; /* VersaTrack's main window menu */
HBITMAP hCompatBitmap; /* handle of copy of screen bitmap */
HBITMAP htBitmap; /* bitmap for drawing text */
HDC hCompatDC; /* correspoding DC's for above */
HDC hAppDC; /* Our window's DC (style is OWNDC) */
HDC htDC; /* DC for bitmap for drawing text */
HPEN hDrawPen[NPAL]; /* All the colored pen handles */
HBRUSH hDrawBrush[NPAL]; /* All the colored brush handles */
HFONT hArial,hHelv,hPica; /* Font of text for htDC */
COLORREF BgColor, FgColor; /* System Defaults for FG & BG */
COLORREF Colors[NPAL]; /* colors we can use... */
HCURSOR hcurSave; /* for previous */
HCURSOR hWait; /* handle of hourglass cursor icon */
HCURSOR hMenuCursor; /* handle of main window menu's cursor */
RECT tRect; /* Text area at bottom of screen */
static HICON hAsterisk, hQuestion; /* Icon handles */
HICON hVersa; /* Main Versatrak Icon Handle */
int width = 750; /* Default width of client area (map) */
int height = 400; /* Default height of client area (map */
int Inst; /* Window Class Instance handle */
int npal, ncolor; /* # of available colors */
int PenColor; /* current pen color */
int BrushColor; /* current brush color */
int TextColor; /* current pen for drawing text */
int CWhite, CBlack; /* Index into pen/brush color tables */
int DefBg, DefFg; /* index into pen/brush color tables */
int currx_client; /* current Client area width */
int curry_client; /* current Client area height */
int extra_x; /* these plus ClRect = total window size */
int extra_y; /* these plus ClRect = total window size */
int ybottom = 20; /* extra space at bottom for text line */
int ytop = 46; /* extra rasters at top for custom menu*/
int maxx_device; /* Max # of pixels the window can have */
int maxy_device; /* Max # of pixels the window can have */
RECT tRect; /* Text area at bottom of screen */
int running; /* TRUE when RTD prediction is running */
int pending; /* user command to do after RTD stops */
int duration_running; /* TRUE when groundtrack is running */
int duration_stop; /* signal to GTR thread to terminate */
int modelflag=NORADSGP4; /* Elset propagation model 0:TLEMEAN 1:SGP4 2:SPD4 */
int NSats,NSites; /* No. of satellites and sites in DB */
void (*diag)(char *, ...); /* printf-line func. for debugging */
static int oct[7] = { 440, 494, 523, 587, 659, 698, 784 }; /* Musical Notes A-G */
mapdata_t mapdata; /* Current map's x and y extents */
static char *mapsuffix; /* Suffix for map file to be drawn */
CRITICAL_SECTION display_mutex; /* Mutex lock for updates to screen */
CRITICAL_SECTION sat_mutex; /* Mutex lock access to sat struct */
extern BOOL DrawMap(void);
extern void vsthelp(void);
extern void SetMButton(UINT, BOOL);
extern char *ErrorString(int);
#ifndef _DEBUG_
void nullfunc(char *s, va_list va) { }
#endif /* _DEBUG_ */
int WINAPI WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
MSG msg;
extern BOOL InitInstance(HANDLE, HANDLE, int);
extern BOOL InitApplication(HANDLE);
select_t *sp;
hInst = hInstance;
if (!InitApplication(hInstance))
return FALSE;
if (!InitInstance(hInstance, hPrevInstance, nCmdShow))
return FALSE;
while (GetMessage(&msg, (UINT)NULL, (UINT)NULL, (UINT)NULL)) {
for (sp = selInfo; sp; sp = sp->sl_next)
if (sp->rtdhwnd && msg.hwnd == sp->rtdhwnd)
if (IsDialogMessage(sp->rtdhwnd, &msg))
goto next;
if (msg.message == VST_NOP)
msg.hwnd = Gwnd;
TranslateMessage(&msg);
DispatchMessage(&msg);
next: ;
}
DestroyObjects();
return 0; /* When program exits */
}
BOOL InitApplication(hInstance)
HANDLE hInstance;
{
WNDCLASS wc;
extern BOOL CALLBACK VersaTrackWindowProc();
hVersa = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_VSTICON));
hAsterisk = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ASTERISK));
hQuestion = LoadIcon(NULL, MAKEINTRESOURCE(IDI_QUESTION));
hWait = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
hcurSave = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_VSTCIRCLE));
sprintf(VersionStr,"VersaTrack V%d.%d",VSTVERSION/10,VSTVERSION%10);
wc.style = CS_OWNDC; /* CS_VREDRAW | CS_HREDRAW; */
wc.lpfnWndProc = (WNDPROC) VersaTrackWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = hVersa;
wc.hCursor = hcurSave;
wc.hbrBackground = NULL;
wc.lpszClassName = "VERSATRACK";
wc.lpszMenuName = NULL;
return RegisterClass(&wc);
}
BOOL InitInstance(hInstance, hPrevInstance, nCmdShow)
HANDLE hInstance, hPrevInstance;
int nCmdShow;
{
HWND hWnd;
hInst = hInstance;
hWnd = CreateWindow("VERSATRACK", VersionStr,
WS_OVERLAPPEDWINDOW|WS_BORDER|WS_CLIPCHILDREN, /* Window style. */
0, 0, width, height,
NULL, /* Overlapped windows have no parent.*/
NULL, /* Use the window class menu. */
hInstance, /* This instance owns this window. */
NULL /* Pointer not needed. */
);
if (hWnd == NULL)
return FALSE;
Gwnd = hWnd;
return TRUE;
}
BOOL CALLBACK
VersaTrackWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int cmd;
select_t *sp;
int (*GetUserInput)(HWND, char *, char *, char *, int);
extern void *LibFunc(const char *), LibClose(void);
static char *busymsg = "Cannot change while busy";
#ifdef _DEBUG_
extern int debugflag;
#endif /* _DEBUG_ */
Gwnd = hWnd;
switch (message) {
case WM_CREATE:
#ifdef _DEBUG_
diag = DebugFunc;
debugflag = 1;
#else /* _DEBUG_ */
diag = nullfunc;
#endif /* _DEBUG_ */
WaitCursor();
InitGraphics();
if (!init_main()) {
PostQuitMessage(0);
break;
}
if (!DrawMap()) {
PostQuitMessage(0);
break;
}
NormCursor();
if (!GetSystemMetrics(SM_MOUSEPRESENT))
fatal("VersaTrack requires the use of a mouse!");
break;
case WM_CANCELMODE:
ReleaseCapture();
break;
case WM_PAINT:
if (IsIconic(hWnd))
goto defaction;
PaintWindow();
break;
case WM_ERASEBKGND:
return 1L;
case WM_GETMINMAXINFO:
((MINMAXINFO *)lParam)->ptMinTrackSize.x = width + extra_x;
((MINMAXINFO *)lParam)->ptMinTrackSize.y = height + extra_y + ytop;
((MINMAXINFO *)lParam)->ptMaxTrackSize.x = width + extra_x;
((MINMAXINFO *)lParam)->ptMaxTrackSize.y = height + extra_y + ytop + ybottom - 1;
break;
case VST_NOP:
#ifdef _DEBUG_
diag("Received VST_NOP %08x %08x\n", wParam, lParam);
#endif /* _DEBUG_ */
break;
case RTD_LONGBEEPUP:
if (InSendMessage())
ReplyMessage(TRUE);
for (cmd = 0; cmd < 8; cmd++) {
Beep(oct[cmd], 40);
Sleep(80);
}
break;
case RTD_LONGBEEPDOWN:
if (InSendMessage())
ReplyMessage(TRUE);
for (cmd = 8; cmd >= 0; cmd--) {
Beep(oct[cmd], 40);
Sleep(80);
}
break;
case EXTM_THEXIT:
WaitForSingleObject((HANDLE) lParam, (DWORD) 5000);
CloseHandle((HANDLE) lParam);
break;
case RTD_THDEXIT:
sp = (select_t *) lParam;
if (sp->rtd_thread_handle) {
WaitForSingleObject(sp->rtd_thread_handle, (DWORD) 5000);
CloseHandle(sp->rtd_thread_handle);
}
rtd_lock(sp);
sp->rtd_thread_handle = NULL;
sp->terminate = sp->running = 0;
rtd_unlock(sp);
if (!rtd_anythread()) {
running = 0;
PostMessage(hWnd, RTD_ALL_THREADS_FINISHED, (WPARAM) 0, (LPARAM) 0);
}
break;
case RTD_WINEXIT:
sp = (select_t *) lParam;
rtd_lock(sp);
sp->rtdhwnd = NULL;
rtd_unlock(sp);
if (!rtd_anythread()) {
running = 0;
PostMessage(hWnd, RTD_ALL_THREADS_FINISHED, (WPARAM) 0, (LPARAM) 0);
}
break;
case RTD_TRUNNING:
case RTD_WRUNNING:
running = 1;
if (rtd_allrunning())
NormCursor();
break;
case RTD_STOPPED:
sp = (select_t *) lParam;
rtd_lock(sp);
sp->flags &= ~SE_THSTOP;
rtd_unlock(sp);
if (rtd_allstopped())
PostMessage(hWnd, RTD_ALL_THREADS_STOPPED, (WPARAM) 0, (LPARAM) 0);
break;
case GTR_QUIT:
duration_running = duration_stop = 0;
WaitForSingleObject(gtr_thread_handle, (DWORD) 15000);
CloseHandle(gtr_thread_handle);
gtr_thread_handle = NULL;
NormCursor();
if (!rtd_anythread()) {
running = 0;
PostMessage(hWnd, RTD_ALL_THREADS_FINISHED, (WPARAM) 0, (LPARAM) 0);
}
break;
case RTD_ALL_THREADS_FINISHED:
if (InSendMessage())
ReplyMessage(TRUE);
NormCursor();
if (pending == PEND_NONE)
break;
switch (pending) {
case PEND_DURATION_PREDICT:
if (!duration_running && !duration_stop)
duration_predict(currentSel);
break;
case PEND_EXITPROGRAM:
goto exitprog;
break;
default:
break;
}
pending = PEND_NONE;
break;
case RTD_ALL_THREADS_STOPPED:
switch(pending) {
case PEND_DRAWMAP:
DrawMap();
break;
default:
break;
}
pending = PEND_NONE;
NormCursor();
break;
case RTD_DORESUME:
SetROP2(hCompatDC, R2_XORPEN);
rtd_allresume();
break;
case WM_SYSCOMMAND:
if (wParam == SC_MINIMIZE)
rtd_savewindowstate();
goto defaction;
case WM_COMMAND:
cmd = LOWORD(wParam);
switch (cmd) {
extern void GetSettings(void), copyrights();
case IDMD_XX1:
case IDMD_XX2:
#ifdef _DEBUG_
{ extern void thdump(BOOL); thdump(FALSE); }
#endif /* _DEBUG_ */
break;
case IDMD_QUIT:
if (running) {
if (yesno("Are you sure you want to exit VersaTrack ?")) {
pending = PEND_EXITPROGRAM;
continuous_display_finish(NULL);
}
break;
}
else goto exitprog;
case IDMD_ABOUT:
copyrights();
break;
case IDMD_HELP:
vsthelp();
break;
case IDMD_GTRFILENAME:
GetUserInput = (void (*)) LibFunc("GetUserInput");
if (GetUserInput == NULL)
usermsg("Invalid Library");
else {
(*GetUserInput)(hWnd,
"Enter Ground Track Report file name:",
gtrfilename, gtrfilename, sizeof(gtrfilename) -1);
}
LibClose();
break;
case IDMD_SETCOLOR:
SetColors();
break;
case IDMD_UNINSTALL:
if (UnInstall(VSTVERSION)) {
if (running) {
pending = PEND_EXITPROGRAM;
continuous_display_finish(NULL);
}
else {
goto exitprog;
}
}
break;
case IDMD_SETTINGS:
GetSettings();
break;
case IDMD_WORLDMAP:
strcpy(mapname,"world");
goto drawmap;
case IDMD_USAMAP:
strcpy(mapname, "usa");
/* FALL THROUGH */
case IDMD_REDRAWMAP:
drawmap:
if (pending)
break;
if (running && !duration_running) {
pending = PEND_DRAWMAP;
WaitCursor();
rtd_allstop();
}
else if (duration_running && !running) {
usermsg("Stop GTR first!");
break;
}
else {
WaitCursor();
DrawMap();
NormCursor();
}
break;
case IDMD_RUNRTD:
continuous_display_init(NULL);
break;
case IDMD_RUNGTR:
if (running && !pending) {
pending = PEND_DURATION_PREDICT;
continuous_display_finish((select_t *)NULL);
}
else if (!duration_running && !duration_stop) {
if (currentSel)
duration_predict(currentSel);
else if (selInfo)
duration_predict(selInfo);
}
break;
case IDMD_RUNRST:
rst ( currentSel ? currentSel : selInfo);
break;
case IDMD_STOP:
if (running && (pending == PEND_NONE)) {
continuous_display_finish((select_t *)NULL);
}
else if (!running && duration_running) {
duration_stop = 1;
}
break;
case IDMD_RADCNTRL:
(void) ServerCreate(&serverInfo[SRV_RADIO], (void *)&radInfo[0]);
break;
case IDMD_ROTCNTRL:
(void ) ServerCreate(&serverInfo[SRV_ROTATOR], (void *)&rotInfo[0]);
break;
}
break;
case WM_LBUTTONUP:
if (!running || duration_running)
break;
sp = checksat(LOWORD(lParam), HIWORD(lParam));
if (sp)
PostMessage(sp->rtdhwnd, RTD_TOGGLE_ICON, (WPARAM)0, (LPARAM)0);
break;
case WM_MOUSEACTIVATE:
return MA_ACTIVATE;
case WM_CLOSE:
if (running) {
if (yesno("Are you sure you want to exit VersaTrack ?")) {
pending = PEND_EXITPROGRAM;
continuous_display_finish(NULL);
if (duration_running)
duration_stop = 1;
}
break;
}
goto defaction;
case WM_DESTROY:
exitprog:
PostQuitMessage(0);
break;
default:
defaction:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0L;
}
/*
* usermsg() - opens a dialog box and posts an informative message. Returns
* when user clicks on the YES button. This is just to write a message.
*/
void
usermsg(msg)
char *msg;
{
strncpy(msgbuf,msg,sizeof(msgbuf)-1);
if (IsIconic(Gwnd)) {
OpenIcon(Gwnd);
EnableWindow(Gwnd, TRUE);
}
DialogBox(hInst, MAKEINTRESOURCE(IDD_MESSAGE), Gwnd, UserMsgProc);
EnableWindow(Gwnd, TRUE);
UpdateWindow(Gwnd);
}
int
yesno(msg)
char *msg;
{
int r;
extern BOOL CALLBACK YesNoProc();
strncpy(msgbuf,msg, sizeof(msgbuf)-1);
if (IsIconic(Gwnd)) {
OpenIcon(Gwnd);
EnableWindow(Gwnd, TRUE);
}
r = DialogBox(hInst, MAKEINTRESOURCE(IDD_YESNO), Gwnd, YesNoProc);
UpdateWindow(Gwnd);
return r;
}
static void
GetSettings()
{
extern BOOL CALLBACK GetSetProc();
static int r;
if (r)
return;
r++;
if (IsIconic(Gwnd))
OpenIcon(Gwnd);
WaitCursor();
DialogBox(hInst, MAKEINTRESOURCE(IDD_SETTINGS), Gwnd, GetSetProc);
NormCursor();
r = 0;
}
/*
* UserMsgProc - dialog box window procedure. This dialog box is used
* to put up various messages for the user. It only has a (big) OK button.
*/
BOOL CALLBACK UserMsgProc(hwnd, message, wParam, lParam)
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
{
int action;
POINT *p;
HDC hdc;
switch(message) {
case WM_INITDIALOG:
p = DialogPos(Gwnd, hwnd);
SendDlgItemMessage(hwnd, IDC_MSGTEXT, WM_SETTEXT, (WPARAM)0, (LPARAM)msgbuf);
SetWindowPos(hwnd, HWND_TOPMOST, (int)p->x, (int)p->y, 0, 0,
SWP_NOSIZE|SWP_SHOWWINDOW);
hdc = GetDC(hwnd);
DrawIcon(hdc, 12, 17, hAsterisk);
ReleaseDC(hwnd, hdc);
break;
case WM_COMMAND:
action = LOWORD(wParam);
if (action == IDOK) {
EndDialog(hwnd, wParam);
return TRUE;
}
break;
case WM_CTLCOLORDLG:
case WM_CTLCOLORSTATIC:
ColorSet(wParam, CBLACK, 14);
return (BOOL) hDrawBrush[14];
default:
break;
}
return FALSE;
}
/*
* YesNoProc - window procedure for messages that solicit a yes or no
* answer from the user.
*/
BOOL CALLBACK YesNoProc(hwnd, message, wParam, lParam)
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
{
int action;
POINT *p;
HDC hdc;
switch(message) {
case WM_INITDIALOG:
p = DialogPos(Gwnd, hwnd);
SendDlgItemMessage(hwnd, IDC_YESNOTEXT, WM_SETTEXT, 0, (LPARAM) msgbuf);
SendMessage(hwnd, DM_SETDEFID, (WPARAM) IDOK, (LPARAM) 0);
SetWindowPos(hwnd, HWND_TOPMOST, (int)p->x, (int)p->y, 0, 0,
SWP_NOSIZE | SWP_SHOWWINDOW);
hdc = GetDC(hwnd);
DrawIcon(hdc, 14, 20, hQuestion);
ReleaseDC(hwnd, hdc);
break;
case WM_COMMAND:
action = LOWORD(wParam);
if (action == IDOK || action == IDCANCEL) {
EndDialog(hwnd, (LOWORD(wParam) == IDOK) ? TRUE : FALSE);
SetFocus(GetParent(hwnd));
EnableWindow(GetParent(hwnd), TRUE);
return TRUE;
}
break;
case WM_CTLCOLORSTATIC:
case WM_CTLCOLORDLG:
ColorSet(wParam, 11, 7); /* 10=light yellow, 6=dark cyan, 5=dark magenta */
return (BOOL) hDrawBrush[7];
}
return FALSE;
}
/*
* Refresh window's actual client area from our copy, based upon the current
* update region passed to us by Windows.
*/
static void
PaintWindow()
{
RECT UR;
PAINTSTRUCT ps;
if (GetUpdateRect(Gwnd, &UR, FALSE) == FALSE)
return;
(void) BeginPaint(Gwnd, &ps);
BitBlt(ps.hdc, (int)UR.left, (int)UR.top, (int)UR.right,
(int)UR.bottom, hCompatDC, (int)UR.left, (int)UR.top, SRCCOPY);
EndPaint(Gwnd, &ps);
}
/*
* InitGraphics() - one-time initialization to set up all the graphics
* related parameters, arrays, colors, DC handles, mapping modes, etc.
*/
static void
InitGraphics()
{
int i;
mapsuffix_t *msp;
LOGPEN lpen;
LOGBRUSH lbrush;
BgColor = GetSysColor(COLOR_WINDOW);
FgColor = GetSysColor(COLOR_WINDOWTEXT);
maxx_device = GetSystemMetrics(SM_CXSCREEN);
maxy_device = GetSystemMetrics(SM_CYSCREEN);
#ifdef _DEBUG_
diag("device maximum width %d\n", maxx_device);
diag("device maximum height %d\n", maxy_device);
#endif
extra_x = GetSystemMetrics(SM_CXFRAME) * 2;
extra_y = GetSystemMetrics(SM_CYFRAME) * 2 +
GetSystemMetrics(SM_CYCAPTION);
hAppDC = GetDC(Gwnd);
hCompatDC = CreateCompatibleDC((HDC)NULL);
htDC = CreateCompatibleDC((HDC)NULL);
htBitmap = CreateCompatibleBitmap(hAppDC, 300, 24); /* for drawing text */
ASSERT(hAppDC);
ASSERT(hCompatDC);
ASSERT(htDC);
ASSERT(htBitmap);
SelectObject (htDC, htBitmap);
hArial = CreateFont (12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "Helvetica" );
hHelv = CreateFont (16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "Helv" );
hPica = CreateFont (12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "Courier" );
ASSERT(hArial);
ASSERT(hHelv);
ASSERT(hPica);
GdiSetBatchLimit(1);
SetBkMode(htDC, TRANSPARENT);
SetMapMode(htDC, MM_ISOTROPIC);
SetWindowExtEx(htDC, 300, 24, NULL);
SetViewportExtEx(htDC, 300, 24, NULL);
SetBkMode(hCompatDC, OPAQUE);
ncolor = NPAL;
CBlack = DefBg = 0;
CWhite = DefFg = 15;
for (i=0; i < ncolor; i++) {
Colors[i] = GetNearestColor(hAppDC, DefColors[i]);
if (Colors[i] == RGB(0,0,0))
CBlack = i;
if (Colors[i] == RGB(255,255,255))
CWhite = i;
if (Colors[i] == BgColor)
DefBg = i;
if (Colors[i] == FgColor)
DefFg = i;
lpen.lopnStyle = PS_SOLID;
lpen.lopnWidth.x = PENWIDTH;
lpen.lopnWidth.y = 0;
lpen.lopnColor = Colors[i];
if ((hDrawPen[i] = CreatePenIndirect(&lpen)) == NULL)
fatal("Can't create Pen");
lbrush.lbStyle = BS_SOLID;
lbrush.lbHatch = 0;
lbrush.lbColor = Colors[i];
if ((hDrawBrush[i] = CreateBrushIndirect(&lbrush)) == NULL)
fatal("Can't create Brush");
}
/*
* Default map file name suffix. If no match, assume custom name...
*/
mapsuffix = "oem";
for (msp = mapSuffix; msp->ms_suffix; msp++)
if ((msp->ms_x == maxx_device) && (msp->ms_y == maxy_device))
mapsuffix = msp->ms_suffix;
while (ShowCursor(FALSE) >=0 ) ; /* remove anomalous show states */
ShowCursor(TRUE);
/* Default ssp, sat annotatation, and ground trk line colors */
MakeBrush(hCompatDC, BrushColor=15); /* White */
MakePen(hCompatDC, PenColor=8); /* Light Grey */
TextColor = 14; /* Light Cyan */
}
void
MakePen(hdc,index)
HDC hdc;
int index;
{
if ((index < 0) || (index >= ncolor))
index = CWHITE;
SelectObject(hdc, (HGDIOBJ) hDrawPen[index]);
}
void
MakeBrush(hdc, index)
HDC hdc;
int index;
{
if ( index < 0 || index > ncolor )
index = DEFBG;
SelectObject(hdc, (HGDIOBJ) hDrawBrush[index]);
}
void
blankBottom()
{
tRect.top = height + ytop + 2; /* +2 allows for an unpainted(black) separating raster */
tRect.bottom = tRect.top + ybottom;
tRect.left = 0;
tRect.right = tRect.left + width;
FillRect(hCompatDC, &tRect, hDrawBrush[8]);
}
static BOOL
DrawMap()
{
HBITMAP htmp;
HDC htmpDC;
BOOL mapchanged;
extern BOOL CALLBACK VSTMenuProc();
extern void *LibFunc(const char *), LibClose(void);
HANDLE (*ReadBitmap)(int, char *, int, int *, int *, mapdata_t *);
#ifdef MAPALIGN
extern void MapPoint(double, double, int, char *);
#endif
sprintf(tmpbuf, "%s%s.map", mapname, mapsuffix);
mapchanged = strcmp(mapfilename, tmpbuf) != 0;
if (mapchanged)
strncpy(mapfilename, tmpbuf, sizeof(mapfilename)-1);
sprintf(tmpbuf, "%s\\%s", datadir, mapfilename);
#ifdef _DEBUG_
diag("Drawing map from %s\n", tmpbuf);
#endif /* _DEBUG_ */
ReadBitmap = (void (*)) LibFunc("ReadDIB");
if (ReadBitmap == NULL) {
LibClose();
usermsg(dllinvalidmsg);
return FALSE;
}
htmp = (HBITMAP) (*ReadBitmap)(VSTVERSION, tmpbuf, 0, &width, &height, &mapdata);
if (htmp == NULL) {
LibClose();
sprintf(tmpbuf, "Cannot open/read map file %s", mapfilename);
usermsg(tmpbuf);
UnInstall(VSTVERSION);
return FALSE;
}
#ifdef DEBUG
diag("map file opened. Width %d height %d\n", width, height);
#endif /* _DEBUG_ */
if ((width > maxx_device) || (height > maxy_device)) {
LibClose();
sprintf(tmpbuf, "%s not suitable for current display resolution", mapfilename);
usermsg(tmpbuf);
UnInstall(VSTVERSION);
return FALSE;
}
if (mapdata.m_version > VSTVERSION)
usermsg("Map may be incompatible with this VersaTrack version.");
display_lock();
if (mapchanged) {
if (hCompatBitmap)
DeleteObject(hCompatBitmap);
hCompatBitmap = CreateCompatibleBitmap(hAppDC,
width, height + ytop + ybottom);
SelectObject(hCompatDC, hCompatBitmap);
}
htmpDC = CreateCompatibleDC((HDC)NULL);
if ((hCompatBitmap == NULL) || (htmpDC == NULL)) {
display_unlock();
usermsg("Cannot Create Device Context or Compatible Bitmap");
LibClose();
return FALSE;
}
SelectObject(htmpDC, htmp);
BitBlt(hCompatDC, 0, ytop, width, height, htmpDC, 0, 0, SRCCOPY);
DeleteObject(htmp);
DeleteObject(htmpDC);
LibClose();
blankBottom();
setwsize(Gwnd, FALSE);
SetMapMode(hCompatDC, MM_ISOTROPIC);
SetWindowExtEx(hCompatDC, width, height, NULL);
SetViewportExtEx(hCompatDC, width, height, NULL);
RedrawScreen(NULL);
display_unlock();
#ifdef MAPALIGN
MapPoint(60.0, 45.0, SRCPAINT, "X"); /* southern tip of GreenLand (approx) */
MapPoint(38.8975, 77.0092, SRCPAINT, "Washington");
MapPoint(29.76, 95.36, SRCPAINT, "Houston");
MapPoint(37.3378, 121.89, SRCPAINT, "San Jose");
#endif
if (!hDlgMenu)
hDlgMenu = CreateDialog(hInst, MAKEINTRESOURCE(IDD_VSTMENU), Gwnd, VSTMenuProc);
if (running)
PostMessage(Gwnd, RTD_DORESUME, (WPARAM) 0, (LPARAM) 0);
return TRUE;
}
static void
DestroyObjects() /* half-hearted */
{
int i;
select_t *sp;
void *vp;
extern void ServerDestroy(void);
WaitCursor();
ServerDestroy();
Sleep(0);
if (hDlgMenu)
DestroyWindow(hDlgMenu);
if (rsthwnd)
DestroyWindow(rsthwnd);
if (htBitmap)
DeleteObject(htBitmap);
if (htDC)
DeleteObject(htDC);
if (hCompatBitmap)
DeleteObject(hCompatBitmap);
if (hCompatDC)
DeleteObject(hCompatDC);
for (i=0; i<ncolor; i++) {
if (hDrawBrush[i])
DeleteObject(hDrawBrush[i]);
if (hDrawPen[i])
DeleteObject(hDrawPen[i]);
}
for (sp = selInfo; sp; sp = (select_t *) vp) {
vp = (void *) sp->sl_next;
GlobalFree((void *)sp->sl_rp);
GlobalFree((void *)sp->sl_tp);
DeleteCriticalSection(&sp->rtd_mutex);
GlobalFree((void *) sp);
}
if (satInfo) {
for (i=0; satInfo[i]; i++) {
if (satInfo[i]->s_modep)
GlobalFree((void *) satInfo[i]->s_modep);
GlobalFree((void *) satInfo[i]);
}
GlobalFree(satInfo);
}
if (siteInfo) {
for (i=0; siteInfo[i]; i++) {
GlobalFree((void *) siteInfo[i]->c_name);
GlobalFree((void *) siteInfo[i]->c_locale);
GlobalFree((void *) siteInfo[i]);
}
GlobalFree(siteInfo);
}
DeleteCriticalSection(&display_mutex);
DeleteCriticalSection(&sat_mutex);
NormCursor();
EnableWindow(GetParent(Gwnd), TRUE);
SetFocus(GetParent(Gwnd));
}
/*
* fatal - is called when an API routine returns an error when we
* don't expect one. For example, we cant create a bitmap, or cant
* get the dimensions of the client area (!!). Normally there is
* nothing else to do except to terminate the program. We do make
* an attempt to put up a message box before exiting.
*/
void
fatal(s)
char *s;
{
char xbuf[256];
sprintf(xbuf,"UNRECOVERABLE ERROR: %s (%s)",s,ErrorString(GetLastError()));
usermsg(s);
DestroyObjects();
ExitProcess(1);
}
POINT *
DialogPos(pwnd, cwnd)
HWND pwnd, cwnd; /* position cwnd in center of pwnd */
{
RECT pr,cr;
static POINT p;
GetClientRect(pwnd,&pr);
GetClientRect(cwnd,&cr);
p.x = p.y = 0;
ClientToScreen(pwnd,&p); /* upper left corner of parent on screen */
if ((p.x < 20) || (p.x + (pr.right - pr.left)) > (maxx_device+20)) {
pr.left = 0;
pr.right = maxx_device;
p.x = 0;
}
if ((p.y < 20) || (p.y + (pr.bottom - pr.top)) > (maxy_device+20)) {
pr.top = 0;
pr.bottom = maxy_device;
p.y = 0;
}
p.x += ((pr.right - pr.left) - (cr.right - cr.left)) / 2;
p.y += ((pr.bottom - pr.top) - (cr.bottom - cr.top + extra_y)) / 2;
return &p;
}
#if 0
static int
OppositeColor(c)
int c;
{
int i;
int cc = Colors[c] ^ 0xffffff;
for (i=0; i< ncolor; i++)
if ((int)Colors[i] == cc)
return i;
return c;
}
#endif
#ifdef MAPALIGN
static void
MapPoint(lat, lon, op, name)
double lat, lon;
int op;
char *name;
{
RECT r;
int x, y, dummy;
SIZE sz;
extern void convcoord(double, double, int *, int *);
convcoord(lat, lon, &x, &y);
display_lock();
Ellipse(hCompatDC, x - 3, y - 3, x + 3, y + 3);
DrawTextStr(hCompatDC, x + 5, y - 9, op, TextColor, CBLACK, hArial, name, &sz);
r.left = x - 4;
r.right = r.left + 8 + sz.cx + 1;
r.top = y - 10;
r.bottom = r.top + MAX(12, sz.cy) + 1;
RedrawScreen(&r)
display_unlock();
}
#endif
void
DrawTextStr(HDC hDC, int x, int y, int op, int textcolor, int bkcolor, HFONT hfont, char *msg, SIZE *sizep)
{
RECT r;
SIZE sz;
int len = strlen(msg);
if (sizep == NULL)
sizep = &sz;
SelectObject(htDC, hfont);
GetTextExtentPoint(htDC, msg, len, sizep);
r.left = r.top = 0;
r.right = sizep->cx + 1;
r.bottom = sizep->cy + 2;
FillRect(htDC, &r, hDrawBrush[bkcolor]);
ColorSet((WPARAM) htDC, textcolor, bkcolor);
TextOut (htDC, 0, 0, msg, len);
BitBlt(hDC, x, y, sizep->cx, sizep->cy, htDC, 0, 0, op);
}
void
ColorSet(wp, tcol, bkcol)
WPARAM wp;
int tcol, bkcol;
{
SetBkColor((HDC) wp, Colors[bkcol]);
SetTextColor((HDC) wp, Colors[tcol]);
}
void
NormCursor()
{
SetWindowText(Gwnd, VersionStr);
SetCursor(hcurSave);
SetClassLong(Gwnd, GCL_HCURSOR, (LONG) hcurSave);
}
void
WaitCursor()
{
SetCursor(hWait);
SetClassLong(Gwnd, GCL_HCURSOR, (LONG) hWait);
SetWindowText(Gwnd,"Please Wait...");
}
void
setwsize(hWnd, flag)
HWND hWnd;
BOOL flag;
{
int wysize, wxsize;
wysize = height + extra_y + ytop + ((flag) ? ybottom-1 : 0);
if (wysize > maxy_device) {
wysize = maxy_device;
}
wxsize = width + extra_x;
if (wxsize > maxx_device)
wxsize = maxx_device;
#ifdef _DEBUG_
diag("map: minX %lf maxX %lf minY %lf maxY %lf\n",
mapdata.m_minx, mapdata.m_maxx, mapdata.m_miny, mapdata.m_maxy);
#endif /* _DEBUG_ */
ScaleX = (double)width / (mapdata.m_maxx - mapdata.m_minx);
ScaleY = (double)height / (mapdata.m_maxy - mapdata.m_miny);
SetWindowPos(hWnd, 0, (int)0, (int)0, wxsize, wysize,
SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
}
static void vsthelp()
{
PROCESS_INFORMATION pinfo;
STARTUPINFO si;
char *cp;
BOOL r;
for (cp = (char *)&si; cp < ((char *)&si + sizeof si);)
*cp++ = 0;
si.lpTitle = "VersaTrack Help";
si.dwXSize = width;
si.dwYSize = height / 2;
si.dwXCountChars = 90;
si.dwYCountChars = 26;
si.wShowWindow = SW_SHOW;
si.dwFlags = STARTF_USESIZE | STARTF_USEPOSITION | STARTF_USESHOWWINDOW |
STARTF_USECOUNTCHARS;
sprintf(tmpbuf,"winhlp32 %s\\versatrk.hlp", datadir);
r = CreateProcess(NULL, tmpbuf, NULL, NULL, TRUE, IDLE_PRIORITY_CLASS,
datadir, NULL, &si, &pinfo);
if (r == FALSE) {
sprintf(tmpbuf,"Unable to create winhlp32. Error code %d",GetLastError());
usermsg(tmpbuf);
}
}
static BOOL CALLBACK
VSTMenuProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_INITDIALOG:
SendDlgItemMessage(hWnd, IDMD_RADCNTRL, WM_SETTEXT, (WPARAM)0,
(LPARAM) (radInfo ? radInfo[0].rad_name : "Radio ?"));
SendDlgItemMessage(hWnd, IDMD_ROTCNTRL, WM_SETTEXT, (WPARAM)0,
(LPARAM) (rotInfo ? rotInfo[0].rot_name : "Rotator ?"));
SetWindowPos(hWnd, 0, 0, 0, 0, 0,
SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
hMenuCursor = (HCURSOR) GetClassLong(hWnd, GCL_HCURSOR);
break;;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED) {
if (LOWORD(wParam) == IDMD_PROPMODEL) {
if (running || duration_running)
usermsg("Stop RTD and/or GTR first!");
else if (modelflag == TLEMEAN) {
SendDlgItemMessage(hWnd, IDMD_PROPMODEL, WM_SETTEXT,
(WPARAM) 0, (LPARAM) "SGP4");
modelflag = NORADSGP4;
}
else if (modelflag == NORADSGP4) {
SendDlgItemMessage(hWnd, IDMD_PROPMODEL, WM_SETTEXT,
(WPARAM) 0, (LPARAM) "TLE Mean");
modelflag = TLEMEAN;
}
return TRUE;
}
PostMessage(Gwnd, WM_COMMAND, wParam, lParam);
return TRUE;
}
break;
case WM_CTLCOLORBTN:
case WM_CTLCOLORDLG:
ColorSet(wParam, CWHITE, 8);
return (BOOL) hDrawBrush[8];
case WM_CLOSE:
return TRUE;
}
return FALSE;
}
void
RedrawScreen(RECT *rp)
{
InvalidateRect(Gwnd, rp, FALSE);
#if 0
UpdateWindow(Gwnd);
#else
RedrawWindow(Gwnd, rp, NULL,
RDW_NOERASE|RDW_INTERNALPAINT|RDW_INVALIDATE|RDW_UPDATENOW);
#endif
}